package com.lanchetech.merchant.service.impl;

import com.lanchetech.bean.request.CountByTimeReq;
import com.lanchetech.bean.request.HomeStatisticsReq;
import com.lanchetech.bean.request.SpuSellStatisticsReq;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.AfterSaleStatusEnum;
import com.lanchetech.common.enums.OrdersStatusEnum;
import com.lanchetech.common.enums.TenantWithdrawStatusEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.merchant.service.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    AfterSaleMapper afterSaleMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    ShopStatisticsMapper shopStatisticsMapper;

    @Autowired
    ShopAmountMapper shopAmountMapper;

    @Autowired
    ShopMapper shopMapper;

    @Autowired
    ShopCollectionMapper shopCollectionMapper;

    @Autowired
    FreezeAmountMapper freezeAmountMapper;

    @Autowired
    TenantWithdrawMapper tenantWithdrawMapper;

    @Autowired
    OrderSkuMapper orderSkuMapper;

    @Autowired
    SpuStatisticsMapper spuStatisticsMapper;

    @Autowired
    UserMapper userMapper;

    public Date getDateStart(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public Date getDateEnd(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    @Override
    public ResultData<MerchantHomeStatisticsVO> getDataStatistics(HomeStatisticsReq req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long tenantId = merchant.getTenantId();
        MerchantHomeStatisticsVO vo = new MerchantHomeStatisticsVO();
        vo.setShop(shopMapper.selectByPrimaryKey(tenantId));
        Date date = new Date();//取时间
        Calendar calendar = Calendar.getInstance();

        ShopStatistics shopStatistics = shopStatisticsMapper.findOneByShopId(tenantId);
        Shop shop = shopMapper.selectByPrimaryKey(tenantId);
        Long shopId = shop.getId();
        calendar.setTime(date);
        Date todayStart = getDateStart(calendar);
        vo.setTotalOrder(ordersMapper.countByTenantId(tenantId));
        vo.setDeliveries(ordersMapper.countByStatusAndDeliveriesAndTenantId(OrdersStatusEnum.PAID.getStatus(), tenantId));
        BigDecimal todayAmount = ordersMapper.sumByTimeRangeAndTenantId(todayStart, date, tenantId);
        vo.setTodayAmount(todayAmount == null ? BigDecimal.ZERO : todayAmount);
        vo.setTodayRefundCount(ordersMapper.countByTimeRangeAndTenantId(todayStart, date, tenantId));
        vo.setShopType(shop.getType());

        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);
        Date yesterdayStart = getDateStart(calendar);
        Date yesterdayEnd = getDateEnd(calendar);
        BigDecimal yesterdayAmount = ordersMapper.sumByTimeRangeAndTenantId(yesterdayStart, yesterdayEnd, tenantId);
        vo.setYesterdayAmount(yesterdayAmount == null ? BigDecimal.ZERO : yesterdayAmount);
        vo.setYesterdayRefundCount(ordersMapper.countByTimeRangeAndTenantId(yesterdayStart, yesterdayEnd, tenantId));
        vo.setTenantFundVO(getTenantFundInfo().getValue());

        //订单数据统计
        TenantSaleStatisticsVO tenantSaleStatisticsVO = new TenantSaleStatisticsVO();
        Date dateStart = null;
        if (req.getIsTotal() != null && !req.getIsTotal()) {
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.setTime(new Date());
            startCalendar.add(Calendar.DATE, -6);
            dateStart = getDateStart(startCalendar);
        }
        OrderStatisticAmountVO orderStatisticAmountVO = ordersMapper.countByTimeStart(dateStart, shopId);
        tenantSaleStatisticsVO.setOrderCount(orderStatisticAmountVO.getOrderCount());
        tenantSaleStatisticsVO.setSaleAmount(orderStatisticAmountVO.getOrderAmount());
        tenantSaleStatisticsVO.setVisitCount(shopStatistics != null ? shopStatistics.getVisitCount() : 0L);
        tenantSaleStatisticsVO.setCollectionCount(shopCollectionMapper.countByShopId(tenantId));
        vo.setTenantSaleStatistics(tenantSaleStatisticsVO);

        //排名信息
        ShopAmount shopAmount = shopAmountMapper.findOneByShopId(shopId);
        Long totalRank;
        Long sameTotalRank;
        if (shopAmount != null) {
            totalRank = shopAmountMapper.countByAmountGreaterThan(shopAmount.getAmount()) + 1;
            sameTotalRank = shopAmountMapper.countByAmountGreaterThanAndIndustryFirstId(shopAmount.getAmount(), shopAmount.getIndustryFirstId());
        } else {
            totalRank = shopAmountMapper.countAll() + 1;
            sameTotalRank = shopAmountMapper.countByIndustryFirstId(shop.getIndustryFirstId()) + 1;
        }
        vo.setTotalRank(totalRank);
        vo.setSameTotalRank(sameTotalRank);

        return new ResultData<>(vo);
    }

    public ResultData<TenantFundVO> getTenantFundInfo() {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long tenantId = merchant.getTenantId();
        TenantFundVO vo = new TenantFundVO();
        vo.setCoin(BigDecimal.ZERO);
        vo.setPoint(BigDecimal.ZERO);
        vo.setWithdrawProcessing(BigDecimal.ZERO);
        vo.setTotalFreezeAmount(BigDecimal.ZERO);
        vo.setWithdrawSuccess(BigDecimal.ZERO);
        if (tenantId == null) {
            return new ResultData<>(vo);
        }
        Tenant tenant = tenantMapper.selectByPrimaryKey(tenantId);

        if (tenant == null) {
            return new ResultData<>(vo);
        }
        FreezeAmountTotalVO freezeAmountTotalVO = freezeAmountMapper.sumAmountByTenantId(tenant.getId());
        BigDecimal freezeAmount = freezeAmountTotalVO == null ? BigDecimal.ZERO : freezeAmountTotalVO.getTotalFreezeAmount();
        vo.setPoint(tenant.getPoint());
        vo.setCoin(tenant.getCoin());
        vo.setWithdrawProcessing(tenantWithdrawMapper.sumByStatusAndTenantId(TenantWithdrawStatusEnum.PROCESSING.getStatus(), tenantId));
        vo.setWithdrawSuccess(tenantWithdrawMapper.sumByStatusAndTenantId(TenantWithdrawStatusEnum.SUCCESS.getStatus(), tenantId));
        vo.setTotalFreezeAmount(freezeAmount);
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<SpuSellStatisticsVO> getSpuSellStatistics(SpuSellStatisticsReq req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long tenantId = merchant.getTenantId();
        Spu spu = spuMapper.selectByPrimaryKey(req.getSpuId());
        SpuSellStatisticsVO vo = new SpuSellStatisticsVO();
        if (spu.getTenantId().equals(tenantId)) {
            SpuSellStatisticsVO sellVO = orderSkuMapper.getSpuSellStatistics(req);
            if (sellVO != null) {
                vo.setOrderCount(sellVO.getOrderCount());
                vo.setPayAmount(sellVO.getPayAmount());
                vo.setTenantAmount(sellVO.getTenantAmount());
            }
            SpuSellStatisticsVO refundVO = afterSaleMapper.getSpuRefundStatistics(req);
            if (refundVO != null) {
                vo.setRefundCount(refundVO.getRefundCount());
                vo.setRefundAmount(refundVO.getRefundAmount());
            }
            SpuStatisticsSumVO sumVO = spuStatisticsMapper.getSpuStatisticsByTime(spu.getId(), req.getStartTime(), req.getEndTime());
            vo.setUv(sumVO == null ? 0 : sumVO.getUv());
            vo.setPv(sumVO == null ? 0 : sumVO.getPv());
        }
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<OrderStatisticsVO> getOrderStatisticsByYear(Integer year) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long tenantId = merchant.getTenantId();
        OrderStatisticsVO vo = new OrderStatisticsVO();
        if (tenantId != null) {
            Calendar startCalendar = Calendar.getInstance();
            Calendar endCalendar = Calendar.getInstance();
            startCalendar.set(Calendar.YEAR, year);
            startCalendar.set(Calendar.DAY_OF_YEAR, startCalendar.getActualMinimum(Calendar.DAY_OF_YEAR));
            endCalendar.set(Calendar.YEAR, year + 1);
            endCalendar.set(Calendar.DAY_OF_YEAR, endCalendar.getActualMinimum(Calendar.DAY_OF_YEAR));
            Date start = getDateStart(startCalendar);
            Date end = getDateStart(endCalendar);
            vo.setStatisticsVOList(ordersMapper.getOrderStatisticsByYear(start, end, tenantId));
            vo.setYearAmouut(ordersMapper.sumAmountByTimeRange(start, end, tenantId));
            vo.setTotalAmount(ordersMapper.sumCompleteAmount(tenantId));
        }
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<List<LongCountByDateVO>> getRegisterUserCount(CountByTimeReq req) {
        return new ResultData<>(userMapper.getRegisterUserCount(req));
    }

    @Override
    public ResultData<List<SpuVO>> getTopSpu() {
        return new ResultData<>(spuMapper.findTopSpu());
    }

    @Override
    public ResultData<List<LongCountByDateVO>> getOrdersCount(CountByTimeReq req) {
        return new ResultData<>(ordersMapper.getOrdersCount(req));
    }

    @Override
    public ResultData<List<BigDecimalCountByDateVO>> getPayAmountCount(CountByTimeReq req) {
        return new ResultData<>(ordersMapper.getPayAmountCount(req));
    }


}
